import Sortable, { SortableEvent } from "sortablejs";

/**
 * sortable.js 实现拖拽拖拽窗口定位效果
 */

export default function initDraggableAreaBySortable(
    dragElementListContainerSelector: string,
    putAreaElementContainerSelector: string
) {
    let offsetX: number, offsetY: number;
    const handlerDragStart = (e: SortableEvent) => {
        // 记录鼠标在当前元素中的相对坐标
        const pointerEvent = (e as any).originalEvent as PointerEvent;
        offsetX = pointerEvent.offsetX;
        offsetY = pointerEvent.offsetY;
    };
    Sortable.create(document.querySelector(dragElementListContainerSelector)!, {
        group: "sortable",
        animation: 150,
        // 不使用原生拖拽效果，以便可以自定义拖拽时跟随鼠标的元素的样式，原生拖拽API中是元素半透明快照图片
        // 原理是设置一个元素时时计算位置跟随鼠标移动，因此性能没有原生API高
        forceFallback: true,
        fallbackClass: "draging",
        onStart: handlerDragStart
    });

    const handlerDragEnd = (e: SortableEvent) => {
        // 获取鼠标在放置时相对放置元素左上角的坐标
        const { offsetX: x, offsetY: y } = (e as any).originalEvent as PointerEvent;

        const left = x - +offsetX;
        const top = y - +offsetY;

        const maxLeft = e.to.offsetWidth - e.item.offsetWidth;
        const maxTop = e.to.offsetHeight - e.item.offsetHeight;

        e.to.style.position = "relative";
        e.item.style.position = "absolute";

        // 设置放置位置：计算被拖拽元素在放置时相对放置元素左上角的坐标
        e.item.style.left = `${Math.min(Math.max(left, 0), maxLeft)}px`;
        e.item.style.top = `${Math.min(Math.max(top, 0), maxTop)}px`;
    };
    Sortable.create(document.querySelector(putAreaElementContainerSelector)!, {
        group: "sortable", // 要想作为拖拽的放置区，必须设置相同的group
        ghostClass: "ghost",
        forceFallback: true,
        fallbackClass: "draging",
        // 处理外部拖拽到放置区时触发
        onAdd: handlerDragEnd,
        // 处理已经在容器内的拖动
        onStart: handlerDragStart,
        onEnd: handlerDragEnd
    });
}
